{***************************************************************
    SpyGestion  Copyright (C) 2008 Christophe KOALI <nature2gas@gmail.com>
    
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
    
****************************************************************}
unit frmCdRMonitor;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, modPlayerFinal, HttpProt, modSockUtils, StdCtrls,

  modGalaxiePlanetes, //modParsingClass,
  modParsingClassGestion,
  Menus,

  Spin, modBaseType, modGidToStr, modUnitAndDefInfos;

type
  TformCdRMonitor = class(TForm)
    timMonitor: TTimer;
    GroupBox35: TGroupBox;
    Label202: TLabel;
    Label203: TLabel;
    seSystemeSolaire: TSpinEdit;
    seGalaxie: TSpinEdit;
    txtChampDeDebrisMonitor: TMemo;
    GroupBox1: TGroupBox;
    Label1: TLabel;
    Label2: TLabel;
    seCdRSimulationPosition: TSpinEdit;
    seVictimePosition: TSpinEdit;
    cmdSimulation: TButton;
    seIntervalle: TSpinEdit;
    Label3: TLabel;
    cmdObserver: TButton;
    cmdCancel: TButton;
    Label4: TLabel;
    cmdTest: TButton;
    chkAfficherMsgDL: TCheckBox;
    seNiveauCombustion: TSpinEdit;
    Label5: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure cmdSimulationClick(Sender: TObject);
    procedure cmdObserverClick(Sender: TObject);
    procedure cmdCancelClick(Sender: TObject);
    procedure timMonitorTimer(Sender: TObject);
    procedure cmdTestClick(Sender: TObject);
    procedure seIntervalleChange(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
    FCurrentPlayer: TPlayerFinal;

    FMenuItemInMainForm: TMenuItem;
    FCurrCoord: string;


    FSock: THttpCli;

    FDoingJob: boolean;


    FUnitesInformations: TCollectionUnitInfos;

    FCurrentLocalDB: TCollectionGalaxiePlanete;
    FTempDB        : TCollectionGalaxiePlanete;


    FWebDataToPost: string;
    FWebURL       : string;

    FParseurGalaxie: TParsingGestion;

    procedure Status(const Msg: string);


    procedure UpdateView;
    procedure CompareTempAndLocal;

    procedure UpdateMenuCaption(Msg: string);


  public
    { Public declarations }
    function GetMainMenuItem : TMenuItem;
    procedure xOnMainMenuItemClick(Sender: TObject);

    procedure Prepare(player: TPlayerFinal; UnitsInfos: TCollectionUnitInfos);
    procedure SetMenuItem(x: TMenuItem);
  end;

var
  formCdRMonitor: TformCdRMonitor;

implementation

{$R *.dfm}

uses modFormulesDuJeu, modFlotteVaisseauxChoix, ESBDates, gnugettext, modClasses, modGestionDownload;

procedure TformCdRMonitor.xOnMainMenuItemClick(Sender: TObject);
begin
   Show;
end;

function TformCdRMonitor.GetMainMenuItem : TMenuItem;
begin
    Result := FMenuItemInMainForm;
end;

procedure TformCdRMonitor.UpdateMenuCaption(Msg: string);
begin
    if FMenuItemInMainForm = nil then begin
       exit;
    end;

    if FCurrCoord <> '' then begin
       FMenuItemInMainForm.Caption := FCurrCoord + ' - ' + Msg;

    end else begin
       FMenuItemInMainForm.Caption := Msg;

    end;

    
end;

procedure TformCdRMonitor.SetMenuItem(x: TMenuItem);
begin
    FMenuItemInMainForm := x;

    FMenuItemInMainForm.OnClick := xOnMainMenuItemClick;

end;

procedure TformCdRMonitor.CompareTempAndLocal;
var i: integer;
    peLocal, peTemp: PGalaxiePlanete;

    haveSomeChange: boolean;

    dbSwitch: TCollectionGalaxiePlanete;
begin

    haveSomeChange := false;

    for i := 0 to FCurrentLocalDB.Count - 1 do begin
       peLocal := FCurrentLocalDB.Items[i];

       peTemp := FTempDB.Get_Pointeur(peLocal.Location);

       if peTemp = nil then begin
          // erreur
          Status('Erreur: Element local non présent dans les éléments temporaires');
          Continue;
       end;

       if mbtRessourceCdRNonVide(peLocal.Ruines) then begin
          // champ de ruine non vide
          // vérifie si il existe toujours

          if mbtRessourceCdRNonVide(peTemp.Ruines) then begin
             // il existe toujours;
             // vérifie si il a diminué

             if (peTemp.Ruines.Metal < peLocal.Ruines.Metal) or (peTemp.Ruines.Cristal < peLocal.Ruines.Cristal) then begin
                // il a diminué
                Status('Diminution de champ de ruine en: ' + mbtPlanetLocationToStr(peLocal.Location) + format(_(' - Taille originale: Métal: %d, Cristal: %d - Nouvelle taille: Métal: %d, Cristal: %d'), [peLocal.Ruines.Metal, peLocal.Ruines.Cristal, peTemp.Ruines.Metal, peTemp.Ruines.Cristal]));

                seCdRSimulationPosition.Value := peLocal.Location.Position;
                cmdSimulationClick(nil);
                
                haveSomeChange := true;
             end;

          end else begin
             // sinon il a disparu entièrement
             Status('Disparition de champ de ruine en: ' + mbtPlanetLocationToStr(peLocal.Location) + format(_(' - Taille originale: Métal: %d, Cristal: %d'), [peLocal.Ruines.Metal, peLocal.Ruines.Cristal]));
             haveSomeChange := true;
          end;

       end else begin
          // il n'y avait pas de champ de ruine
          // vérifie si il y en a un maintenant

          if mbtRessourceCdRNonVide(peTemp.Ruines) then begin
             // un champ de ruine s'est créé
             Status('Création d''un champ de ruine en: ' + mbtPlanetLocationToStr(peLocal.Location) + format(_(' - Taille: Métal: %d, Cristal: %d'), [peTemp.Ruines.Metal, peTemp.Ruines.Cristal]));
             haveSomeChange := true;

          end;

       end;

    end;

    
    if haveSomeChange then begin
       // met à jour la base de données locale
       // au lieu d'importer la liste, on switch juste les pointeurs
       dbSwitch        := FTempDB;
       FTempDB         := FCurrentLocalDB;
       FCurrentLocalDB := dbSwitch;
    end;

end;

procedure TformCdRMonitor.UpdateView;
label lFin;
var sPageWeb: string;
begin

    if FDoingJob then begin
       exit;
    end;

    FDoingJob := true;

    if FWebURL = '' then begin
       Status('Erreur (non préparé)');
       goto lFin;
    end;

    if FSock.State <> httpReady then begin
       goto lFin;
    end;

    FSock.CtrlSocket.CloseDelayed;
    Application.ProcessMessages;
    FSock.CtrlSocket.Close;
    Application.ProcessMessages;
    

    if chkAfficherMsgDL.Checked then begin
       Status('Vérification...');
    end;

    sPageWeb := FCurrentPlayer.myGETorPOST_InTamponX(FWebURL, FWebDataToPost, FSock);

    if sPageWeb = modDL_ERREUR_DL_STR then begin
       Status('Erreur de téléchargement');
       goto lFin;
    end else if sPageWeb = mcDL_MUST_RELOGIN then begin
       Status('Doit se relogger');
       goto lFin;
    end else if length(sPageWeb) < 50 then begin
       Status('Page web trop petite');
       goto lFin;
    end;

    // on ajoute toujours les pointeurs
    //FParseurGalaxie.DontAddPointeur := false;
    FParseurGalaxie.pGalaxie.DontAddPointeur := false;




    if FParseurGalaxie.ParsingGalaxie(sPageWeb) = false then begin
       // echec
       Status('Echec de parsing');
       goto lFin;
    end;

    FTempDB.Clear;
    FTempDB.CopyFromList(FParseurGalaxie.pGalaxie.ListPlanete);

    // sécurité
    FCurrentLocalDB.DeleteAllExceptThisSystemSolaire(seSystemeSolaire.Value);

    if FTempDB.Count < 15 then begin
       // erreur
       Status('Moins de 15 éléments dans la liste temporaire...');
       goto lFin;
    end;
    if FTempDB.Count > 15 then begin
       // erreur
       Status('Plus de 15 éléments dans la liste temporaire...');
       goto lFin;
    end;

    CompareTempAndLocal;

lFin:
    FDoingJob := false;

end;

procedure TformCdRMonitor.Status(const Msg: string);
begin
    txtChampDeDebrisMonitor.Lines.Add(DateTimeToStr(Now) + ' - ' + Msg);
end;


procedure TformCdRMonitor.timMonitorTimer(Sender: TObject);
begin
    if cmdObserver.Enabled = false then begin
       UpdateView;
    end;

end;

procedure TformCdRMonitor.Prepare(player: TPlayerFinal; UnitsInfos: TCollectionUnitInfos);
begin
    FCurrentPlayer := player;
    FUnitesInformations := UnitsInfos;

    if FWebURL = '' then begin
       suCopySocketHttpInfos(FSock, player.sockHTTP);

       cmdCancelClick(nil);

       FWebDataToPost:= '';
       FWebURL       := '';

    end;

    FMenuItemInMainForm := nil;

    Show;
end;

procedure TformCdRMonitor.seIntervalleChange(Sender: TObject);
begin
    if (cmdObserver.Enabled = false) and (FWebURL <> '') then begin
       timMonitor.Interval := seIntervalle.Value;
    end;

end;

procedure TformCdRMonitor.cmdCancelClick(Sender: TObject);
begin
   timMonitor.Interval := 0;
   cmdObserver.Enabled := true;

   UpdateMenuCaption(_('Arrêté'));

end;

procedure TformCdRMonitor.cmdObserverClick(Sender: TObject);
var i: integer;
    pe: PGalaxiePlanete;
    NbCdr: integer;
begin
   if FCurrentPlayer.IsLoggedAndCanDoSomething = false then begin
      Status(_('Non prêt'));
      exit;
   end;

   Status(_('Préparation...'));

   FCurrCoord := '';

   cmdObserver.Enabled := false;

   FCurrentLocalDB.Clear;
   FCurrentPlayer.ProceedGalaxieScan(FCurrentLocalDB, seGalaxie.Value, seSystemeSolaire.Value, seSystemeSolaire.Value, 0);

   if FCurrentLocalDB.Count < 15 then begin
      // erreur
      cmdObserver.Enabled := true;
      Status(_('Erreur...'));
      exit;
   end;

   // Ne conserve que le bon système solaire
   FCurrentLocalDB.DeleteAllExceptThisSystemSolaire(seSystemeSolaire.Value);

   if FCurrentLocalDB.Count < 15 then begin
      // erreur
      cmdObserver.Enabled := true;
      Status(_('Erreur, le bon système solaire n''a pas été scanné...'));
      exit;
   end;
   if FCurrentLocalDB.Count > 15 then begin
      cmdObserver.Enabled := true;
      Status(_('Erreur, trop d''élément dans la base de données...'));
      exit;
   end;

   NbCdr := 0;

   // maintenant on recherche si il existe un champ de ruine
   for i := 0 to FCurrentLocalDB.Count - 1 do begin
      pe := FCurrentLocalDB.Items[i];

      if (pe.Ruines.Metal > 0) or (pe.Ruines.Cristal > 0) then begin
         // champ de ruine trouvé
         Status(format(_('Champ de ruine en position %d (Métal: %d, Cristal: %d)'), [pe.Location.Position, pe.Ruines.Metal, pe.Ruines.Cristal]));
         Inc(NbCdr);
      end;
   end;

   if NbCdr < 1 then begin
      // aucun cdr
      cmdObserver.Enabled := true;
      Status(_('Aucun champ de ruine trouvé dans ce système solaire'));
      exit;
   end;


    FCurrCoord := format('%d:%d:xx', [seGalaxie.Value, seSystemeSolaire.Value]);

    UpdateMenuCaption(_('En observation'));

    FWebDataToPost := 'session=' + FCurrentPlayer.cParsing.pGalaxie.SessionKey + '&galaxy=' + IntToStr(seGalaxie.Value) + '&system=' + IntToStr(seSystemeSolaire.Value);

    FWebURL := FCurrentPlayer.sockHTTP.URL;
    FSock.Reference  := FCurrentPlayer.sockHTTP.Reference;

    timMonitor.Interval := seIntervalle.Value;
end;

procedure TformCdRMonitor.cmdSimulationClick(Sender: TObject);
var Depart, Cible : TPlanetLocation;

    trajetDistance: integer;
    trajetDuree   : integer;

    Vaisseaux: TCollectionVaisseauSelInfos;
    vRecycleurs: TVaisseauSelInfos;
    peRecycleurs: PUnitInfos;

    iPourcent: integer;

    s: string;

    currDate, retourDate: int64;
begin

    Depart.Galaxie       := seGalaxie.Value;
    Depart.SystemSolaire := seSystemeSolaire.Value;
    Depart.Position      := seVictimePosition.Value;

    Cible := Depart;
    Cible.Position := seCdRSimulationPosition.Value;


    peRecycleurs := FUnitesInformations.Get_Pointeur(CNT_GID_VAISSEAUX_RECYCLEUR);

    if peRecycleurs = nil then begin
       // erreur
       exit;
    end;

    vRecycleurs.GID    := peRecycleurs.GID;
    vRecycleurs.GIDNom := 'Useless';
    vRecycleurs.Max    := 5;
    vRecycleurs.Speed       := mfdgGetRealVitesseReacteurCombustion(peRecycleurs.Vitesse, seNiveauCombustion.Value);
    vRecycleurs.Consomation := peRecycleurs.Consommation;
    vRecycleurs.Capacite    := peRecycleurs.Fret;
    vRecycleurs.AllHiddenInput    := 'hidden=x';
    vRecycleurs.InputNameForChoix := 'inputchoix=y';
    vRecycleurs.QuantiteVoulu     := 4;


    //

    Vaisseaux := TCollectionVaisseauSelInfos.Create;
    Vaisseaux.Add(vRecycleurs);

    trajetDistance := mfdgGetDistance(Depart, Cible);

    currDate := DateTimeToUnix(Now);



    for iPourcent := 1 to 10 do begin
       trajetDuree    := mfdgGetDurationTrajet(trajetDistance, Vaisseaux.GetSpeedUsed, iPourcent * 10, FCurrentPlayer.Conf.UniversSpeedFactorFlotte);

       s := ESBDGetDureeStrings(trajetDuree, true);

       Status('Vitesse ' + IntToStr(iPourcent * 10) + '% -> ' + s + '   Avec retour:' + ESBDGetDureeStrings(trajetDuree * 2, true) );

       retourDate := currDate + trajetDuree;

       Status('-> Retour estimé à ' + DateTimeToStr(UnixToDateTime(retourDate)) + ' (heure locale)');

    end;


    Vaisseaux.Free;

end;

procedure TformCdRMonitor.cmdTestClick(Sender: TObject);
begin
    cmdTest.Enabled := false;
    UpdateView;
    cmdTest.Enabled := true;
end;

procedure TformCdRMonitor.FormClose(Sender: TObject; var Action: TCloseAction);
begin
   FWebURL := '';
   cmdCancelClick(nil);

   FMenuItemInMainForm.Enabled := false;

   UpdateMenuCaption('Fermé');


end;

procedure TformCdRMonitor.FormCreate(Sender: TObject);
begin
    FSock := THttpCli.Create(Self);

    FCurrentLocalDB := TCollectionGalaxiePlanete.Create;
    FTempDB         := TCollectionGalaxiePlanete.Create;

    FParseurGalaxie := TParsingGestion.Create(nil);

    FDoingJob := false;

end;

procedure TformCdRMonitor.FormDestroy(Sender: TObject);
begin
    FParseurGalaxie.Free;

    FCurrentLocalDB.Free;
    FTempDB.Free;

    FSock.Free;
end;

end.
